package  
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	/**
	 * 混淆数据
	 * @author WLDragon
	 */
	public class MixData 
	{
		private var callBack:Function;
		public var mixStrings:Array = [];
		
		private var version:int;
		private var oldLength:uint;//原始文件长度
		private var abcLength:uint;//doABCTag的长度
		private var abcLengthPosition:uint;//content中保存doABCTag长度的开始位置
		private var beginPosition:uint;//开始混淆的字节位置(string常量开始)
		private var endPosition:uint;//结束混淆的字节位置(string常量结束)
		private var constStrings:Array = [];//新的string常量集
		private var compareTable:Object;
		
		private var characterIndex:uint;//用于生成无重复的字符组合
		private var charSetLength:int;//字符集的长度
		//private const CHAR_SET:String = "_abcdefghijklmnopqrstuvwxyz";//混淆用的字符集，调试时用
		private const CHAR_SET:String = "~!@#$%^&*()+-=<>?{}[]|:,./;";//混淆用的字符集，发布时用
		private const KEY_WORDS:Array = ["as","do","if","in","is","var","try","use","new","for","set","get"];//as3基本关键词
		
		public function MixData(completeCallBack:Function) 
		{
			this.callBack = completeCallBack;
			this.charSetLength = CHAR_SET.length;
		}
		
		public function reset():void
		{
			compareTable = { };
			characterIndex = 0;
			constStrings.length = 0;
		}

		public function mix(data:ByteArray):void 
		{
			data.endian = Endian.LITTLE_ENDIAN;
			
			//读取是否压缩
			var compressFlg:String = data.readUTFBytes(3);
			//读取版本
			version = data.readByte();
			//读取长度
			oldLength = data.readUnsignedInt();
			//读取内容
			var content:ByteArray = new ByteArray();
			content.endian = Endian.LITTLE_ENDIAN;
			data.readBytes(content);
			
			if (compressFlg == "CWS") {
				content.uncompress();
			}
			
			//读取文件大小RECT
			var a:int = ByteUtil.readUB(5, content);
			var Xmin:int = ByteUtil.readSB(a, content);
			var Xmax:int = ByteUtil.readSB(a, content);
			var Ymin:int = ByteUtil.readSB(a, content);
			var Ymax:int = ByteUtil.readSB(a, content);
			ByteUtil.alignByte(content);
			
			//帧频
			var rate:int = content.readShort();
			//总帧数
			var frames:uint = content.readUnsignedShort();
			
			//读取Tag
			readTag(content);
		}
		
		private function readTag(data:ByteArray):void
		{
			while (data.bytesAvailable > 0) {
				var tagInfo:uint = data.readUnsignedShort();
				var type:uint = tagInfo >> 6;
				var len:uint = tagInfo & ((1 << 6) - 1);
				if(len == 0x3F) len = data.readInt();

				if (type == 82) {//82是doABCTag
					abcLength = len;
					abcLengthPosition = data.position - 4;
					var flgs:uint = data.readUnsignedInt();
					var abcName:String = ByteUtil.readString(data);
					parseAbcFile(data);
					break;
				}else {
					data.position += len;
				}
			}
			
			createSWF(data);
		}
		
		private function parseAbcFile(data:ByteArray):void 
		{
			var minor:uint = data.readUnsignedShort();//abcFile的副版本号
			var major:uint = data.readUnsignedShort();//主版本号
			
			//接下来是常量池
			//int
			var n:uint = ByteUtil.readU30(data);
			for (var i:int = 1; i < n; i++) {//从1开始循环，没有0的
				ByteUtil.readS32(data);
			}
			//uint
			n = ByteUtil.readU30(data);
			for (i = 1; i < n; i++) {
				ByteUtil.readU32(data);
			}
			//double
			n = ByteUtil.readU30(data);
			for (i = 1; i < n; i++) {
				data.readDouble();
			}
			//string 这是是混淆的关键
			beginPosition = data.position;
			n = ByteUtil.readU30(data);
			characterIndex = 0;
			for (i = 1; i < n; i++) {
				var s:uint = ByteUtil.readU30(data);
				var v:String = data.readUTFBytes(s);
				if (mixStrings.indexOf(v) > -1) {
					var c:String = getMixCharacter();
					constStrings.push(c);
					compareTable[c] = v;
				} else {
					constStrings.push(v);
				}
			}
			endPosition = data.position;
		}
		
		private function getMixCharacter():String
		{
			var r:String = "";
			var i:int = characterIndex;
			do {
				r += CHAR_SET.charAt(i % charSetLength);
				i = i / charSetLength >> 0;
			}while (i > 0);
			
			characterIndex++;
			if (KEY_WORDS.indexOf(r) > -1) return getMixCharacter();
			return r;
		}
		
		private function createSWF(data:ByteArray):void
		{
			//插入头部分的字节
			data.position = 0;
			var temp:ByteArray = new ByteArray();
			temp.endian = Endian.LITTLE_ENDIAN;
			data.readBytes(temp, 0, beginPosition);
			//插入混淆的部分
			temp.position = temp.length;
			var n:uint = constStrings.length;
			ByteUtil.writeU30(n + 1, temp);
			var buffer:ByteArray = new ByteArray();
			for (var i:int = 0; i < n; i++) {
				var s:String = constStrings[i];
				buffer.clear();
				buffer.writeUTFBytes(s);
				ByteUtil.writeU30(buffer.length, temp);
				temp.writeUTFBytes(s);
			}
			//插入结尾部分
			data.position = endPosition;
			data.readBytes(temp, temp.length);
			//重新计算doABC的长度，混淆后的长度必然比原来的长度要短
			var len:uint = temp.length + 8;
			n = abcLength - (oldLength - len);//新ABC的长度
			temp.position = abcLengthPosition;
			temp.writeInt(n);
			//压缩
			temp.compress();
			//组装SWF（写入头和内容）
			var b:ByteArray = new ByteArray();
			b.endian = Endian.LITTLE_ENDIAN;
			b.writeUTFBytes("CWS");
			//b.writeUTFBytes("FWS");
			b.writeByte(version);
			b.writeUnsignedInt(len);
			b.writeBytes(temp);
			
			//处理对照表
			var a:Array = [];
			for (var k:String in compareTable) {
				a.push(k + " " + compareTable[k]);
			}
			a.sort();
			callBack(b, a.join("\r\n"));
		}
	}

}